home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / What's New? / Software Development Kits / Mac OS USB DDK / MacOS USB DDK 1.0b4 / NeptuneDDK / Examples / CompositeClassDriver / CompositeClassDriver.c next >
Encoding:
C/C++ Source or Header  |  1998-06-26  |  8.7 KB  |  239 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CompositeClassDriver.c
  3.  
  4.     Contains:    Core functionality to Composite Class Driver
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "CompositeClassDriver.h"
  19. extern    usbCompositePBStruct myCompositePBRecord;
  20.  
  21.  
  22. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  23. {
  24.     paramblock->usbReference = theDeviceRef;
  25.     paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  26.     paramblock->pbLength = sizeof(usbCompositePBStruct);
  27.     paramblock->pbVersion = kUSBCurrentPBVersion;
  28.     paramblock->usbWIndex = 0;             
  29.     paramblock->usbBuffer = nil;        
  30.     paramblock->usbStatus = kUSBNoErr;
  31.     paramblock->usbReqCount = 0;
  32.     paramblock->usbActCount = 0;
  33.     paramblock->usbWValue = 0;
  34.     paramblock->usbFlags = 0;
  35. }
  36.  
  37.  
  38. Boolean immediateError(OSStatus err)
  39. {
  40.     return((err != kUSBPending) && (err != kUSBNoErr) );
  41. }
  42.  
  43. void CompositeDeviceInitiateTransaction(USBPB *pb)
  44. {
  45. register usbCompositePBStruct *pCompositePB;
  46. OSStatus myErr;
  47.  
  48.     pCompositePB = (usbCompositePBStruct *)(pb);
  49.     pCompositePB->transDepth++;
  50.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  51.     {
  52.     
  53.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: Illegal Transaction Depth", pCompositePB->pb.usbRefcon);
  54.     }
  55.     do 
  56.     {
  57.         switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction)
  58.         {
  59.             case kGetFullConfiguration0:
  60.                 InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  61.                 pCompositePB->pb.usbWIndex = 0;             /* First try configuration 0, if it doesn't succeed, then try config 1*/
  62.                 
  63.                 pCompositePB->pb.usbRefcon |= kCompletionPending;
  64.                 pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  65.                 myErr = USBGetFullConfigurationDescriptor(pb);
  66.                 if(immediateError(myErr))
  67.                 {
  68.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: USBGetFullConfiguration (#0) - immediate error", myErr);
  69.                 }
  70.                 break;
  71.             
  72.             case kGetFullConfiguration1:
  73.                 InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  74.                 pCompositePB->pb.usbWIndex = 1;             /* Try configuration 1 (some devices seem to expect config 0, others config 1 */
  75.                 pCompositePB->pb.usbRefcon |= kCompletionPending;
  76.                 
  77.                 pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  78.                 myErr = USBGetFullConfigurationDescriptor(pb);
  79.                 if(immediateError(myErr))
  80.                 {
  81.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: USBGetFullConfiguration (#1) - immediate error", myErr);
  82.                 }
  83.                 break;
  84.             
  85.             case kSetConfig:
  86.                 InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  87.                 pCompositePB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);
  88.                 
  89.                 pCompositePB->pb.usbBRequest = kUSBRqSetConfig;
  90.                 pCompositePB->pb.usbWValue = pCompositePB->pFullConfigDescriptor->configValue;         /* Use configuration ID value from descriptor */
  91.                 
  92.                 pCompositePB->pb.usbRefcon |= kCompletionPending;
  93.                 
  94.                 pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  95.                 myErr = USBDeviceRequest(pb);
  96.                 if(immediateError(myErr))
  97.                 {
  98.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: kSetConfig - immediate error", myErr);
  99.                 }
  100.                 break;
  101.                 
  102.             case kNewInterfaceRef:
  103.                 InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  104.                 // Note: pCompositePB->usbWIndex will be set to zero by InitParamBlock
  105.                 // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef
  106.                 pCompositePB->pb.usbWIndex = pCompositePB->interfaceIndex;
  107.                 pCompositePB->pb.usbRefcon |= kCompletionPending;
  108.                 pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  109.  
  110.                 myErr = USBNewInterfaceRef(pb);
  111.                 if(immediateError(myErr))
  112.                 {
  113.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: kNewInterfaceRef - immediate error", myErr);
  114.                 }
  115.                 break;
  116.                 
  117.             default:
  118.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon);
  119.                 pCompositePB->pb.usbRefcon = kUndefined + kExitDriver;
  120.                 break;
  121.         }
  122.     } while (false);
  123.     
  124. // At this point the control is returned to the system.  If a USB transaction
  125. // has been initiated, then it will call the Complete procs
  126. // (below) to handle the results of the transaction.
  127. }
  128.  
  129. void CompositeDeviceCompletionProc(USBPB *pb)
  130. {
  131. register usbCompositePBStruct *pCompositePB;
  132. USBInterfaceDescriptorPtr pInterfaceDescriptor;
  133. UInt32 i;
  134.  
  135.     pCompositePB = (usbCompositePBStruct *)(pb);
  136.     pCompositePB->transDepth--;
  137.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  138.     {
  139.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver - Illegal Transaction Depth", pCompositePB->transDepth);
  140.     }
  141.     
  142.     if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending))
  143.     {
  144.         USBExpertStatus(pCompositePB->pb.usbReference, "\pComposite Driver: Completion Error", pCompositePB->pb.usbStatus);
  145.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver);
  146.         pCompositePB->pb.usbRefcon |= kRetryTransaction;
  147.         pCompositePB->retryCount--;
  148.         if (!pCompositePB->retryCount)
  149.         {
  150.             if (pCompositePB->pb.usbRefcon == kGetFullConfiguration1)
  151.             {
  152.                 pCompositePB->pb.usbRefcon = kGetFullConfiguration0;
  153.             }
  154.             else
  155.             {
  156.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: Too many retries", pCompositePB->pb.usbRefcon);
  157.                 pCompositePB->pb.usbRefcon = kExitDriver;
  158.                 return;
  159.             }
  160.         }
  161.     }
  162.     else
  163.     {
  164.         pCompositePB->pb.usbRefcon &= ~kRetryTransaction;
  165.         pCompositePB->retryCount = kCompositeRetryCount;
  166.     }
  167.  
  168.     if (pCompositePB->pb.usbRefcon & kCompletionPending)             
  169.     {                                                
  170.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver);
  171.         switch(pCompositePB->pb.usbRefcon)
  172.         {
  173.             case kGetFullConfiguration0:
  174.             case kGetFullConfiguration1:
  175. //                DebugStr("\pCheck power");
  176.                 pCompositePB->pFullConfigDescriptor = pCompositePB->pb.usbBuffer;
  177.                 if (pCompositePB->pFullConfigDescriptor == nil)
  178.                 {
  179.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: USBGetFullConfiguration - pointer is nil", pCompositePB->pb.usbRefcon);
  180.                     pCompositePB->pb.usbRefcon = kExitDriver;
  181.                     break;
  182.                 }
  183.                 
  184.                 BlockCopy(   (void *)pCompositePB->pFullConfigDescriptor, (void *)(&(pCompositePB->partialConfigDescriptor)), (Size)(sizeof(USBConfigurationDescriptor) )  );
  185.                 if (pCompositePB->pFullConfigDescriptor->maxPower <= pCompositePB->busPowerAvailable)
  186.                 {
  187.                     pCompositePB->pb.usbRefcon = kSetConfig;
  188.                 }
  189.                 else
  190.                 {
  191.                     USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, pCompositePB->pFullConfigDescriptor->maxPower);
  192.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBDevicePowerProblem, "\pComposite Driver - Insufficient power for device", pCompositePB->pb.usbRefcon);
  193.                     pCompositePB->pb.usbRefcon = kExitDriver;
  194.                 }
  195.                 break;
  196.                 
  197.             case kSetConfig:
  198.                 
  199.                 for (i=0; i < pCompositePB->partialConfigDescriptor.numInterfaces; i++)
  200.                 {
  201.                     pCompositePB->interfaceRefArray[i] = 0;
  202.                     GetInterfaceDescriptor(pCompositePB->pFullConfigDescriptor, (UInt32)i, &pInterfaceDescriptor);
  203.                     BlockCopy((void *)pInterfaceDescriptor, (void *)(&(pCompositePB->interfaceDescriptors[i])), (Size)(pInterfaceDescriptor->length));
  204.                 }
  205.                 pCompositePB->interfaceIndex = 0;
  206.                 pCompositePB->interfaceCount = pCompositePB->partialConfigDescriptor.numInterfaces;
  207.                 pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  208.                 break;
  209.                 
  210.             case kNewInterfaceRef:
  211.                 pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex] = pCompositePB->pb.usbReference;
  212.                 
  213.                 USBExpertInstallInterfaceDriver(pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex], &pCompositePB->deviceDescriptor, &pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex], pCompositePB->deviceRef, 0);
  214.                 pCompositePB->interfaceIndex++;
  215.                 if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount)
  216.                 {
  217.                     pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  218.                 }
  219.                 else
  220.                 {
  221.                     pCompositePB->pb.usbRefcon = kExitDriver;
  222.                 }
  223.                 break;
  224.             
  225.             default:
  226.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon);
  227.                 pCompositePB->pb.usbRefcon = kExitDriver;
  228.                 break;
  229.         }
  230.     }
  231.     if (!(pCompositePB->pb.usbRefcon & kExitDriver))
  232.         CompositeDeviceInitiateTransaction(pb);
  233.  
  234.     pCompositePB->okayToFinalizeFlag = true;
  235.     pCompositePB->disposeCompletedFlag = true;
  236. }
  237.  
  238.  
  239.